{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "94918367-ea66-4bc4-9913-c704f45686ee",
   "metadata": {},
   "source": [
    "# Plotting Extensions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2ce662e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "from hvplot.sample_data import us_crime"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd615c60",
   "metadata": {},
   "source": [
    "hvPlot allows to generate plots with three different plotting extensions: [Bokeh](https://docs.bokeh.org), [Matplotlib](https://matplotlib.org/) and [Plotly](https://plotly.com/). Support for Maplotlib and Plotly was added in version 0.8.0, before which Bokeh was the only option available and is as such kept as the default plotting extension.\n",
    "\n",
    "## Loading plotting extensions\n",
    "\n",
    "Importing hvPlot accessors as shown throughout the documentation (e.g. `import hvplot.pandas`, `import hvplot.xarray`, ...) loads by default the Bokeh plotting extension. The `extension` function can be used after this first import to additionally load the Matplotlib and Plotly plotting extensions, or just one of them. The currently active extension is the first one passed to `extension()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "78a9f5b8",
   "metadata": {},
   "outputs": [],
   "source": [
    "import hvplot.pandas  # This import automatically loads the Bokeh extension."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "615a4574",
   "metadata": {},
   "outputs": [],
   "source": [
    "hvplot.extension('matplotlib', 'plotly')  # This call loads the Matplotlib (the active one) and Plotly extensions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d4aa473",
   "metadata": {},
   "outputs": [],
   "source": [
    "us_crime.hvplot(x='Year', y='Violent Crime rate')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9724c0af",
   "metadata": {},
   "source": [
    "## Switching the plotting extension\n",
    "\n",
    "The `output` function allows to switch the plotting extension by setting the `backend` parameter. It must be called **after** importing an accessor (e.g. `import hvplot.pandas`) and calling to `extension`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "66ba89b0",
   "metadata": {},
   "outputs": [],
   "source": [
    "hvplot.output(backend='plotly')\n",
    "\n",
    "us_crime.hvplot(x='Year', y='Violent Crime rate')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0111ae1a",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-warning\" role=\"alert\">\n",
    "    The <code>extension</code> function could also be used to switch the plotting extension. You should however prefer <code>output</code> as any call to <code>extension</code> actually internally loads code in the output of the cell where it is executed, which can significantly increase the notebook size if <code>extension</code> is called in multiple cells.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20eb7da9",
   "metadata": {},
   "source": [
    "## Plot styling options\n",
    "\n",
    "On top of the parameters part of `.hvplot()`'s API, a plot can be further customized by providing detailed styling options. By default, i.e. without calling `hvplot.extension()`, the accepted styling options are those of Bokeh, such as `line_dash='dashed'`. When another extension is set with either `extension` or `output` the styling options of that extension are expected, e.g. `linestyle='dashed'` for Matplotlib."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0282171e",
   "metadata": {},
   "outputs": [],
   "source": [
    "hvplot.output(backend='bokeh')\n",
    "us_crime.hvplot(x='Year', y='Violent Crime rate', line_dash='dashed')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6078c7ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "hvplot.output(backend='matplotlib')\n",
    "us_crime.hvplot(x='Year', y='Violent Crime rate', linestyle='dashed')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bcf1f408",
   "metadata": {},
   "source": [
    "It is also possible to generates plots with either Matplotlib or Plotly that are constructed with Bokeh options. This can be used for instance to create plots previously generated with Bokeh with another backend, without having to change any parameter. The only change required is to declare Bokeh as the compatible extension with `hvplot.extension('matplotlib', compatibility='bokeh')`, preferably at the beginning of the notebook."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21701d52",
   "metadata": {},
   "outputs": [],
   "source": [
    "hvplot.extension('matplotlib', compatibility='bokeh')\n",
    "violent_crime = us_crime.hvplot(x='Year', y='Violent Crime rate', line_dash='dashed')\n",
    "violent_crime"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1371e7df",
   "metadata": {},
   "outputs": [],
   "source": [
    "violent_crime.opts.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96ed79b6",
   "metadata": {},
   "source": [
    "You can see that `line_dash='dashed'` has been internally converted to `linestyle='dashed'` that is a valid option for the Matplotlib plotting extension. Note that support for all Bokeh options is currently incomplete and will continue to be improved while equivalent support for Plotly and Matplotlib is planned for a future release"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ac83784",
   "metadata": {},
   "source": [
    "## Obtaining the underlying figure object "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "706832e4",
   "metadata": {},
   "source": [
    "In some cases it can be convenient to construct a plot with hvPlot and then get a handle on the figure object of the underlying plotting library to further customize the plot or to embed it in some more complex application. The `render` function allows to get a handle on the figure object. The following examples show that it's possible to use the API of Bokeh, Matplotlib or Plotly to update the title of the `violent_crime` plot."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c20891e6",
   "metadata": {},
   "outputs": [],
   "source": [
    "violent_crime = us_crime.hvplot(x='Year', y='Violent Crime rate')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d2f09071",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bokeh.io import show\n",
    "\n",
    "bk_fig = hvplot.render(violent_crime, backend='bokeh')\n",
    "bk_fig.title = 'Violent crime'\n",
    "show(bk_fig)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5753ad3a",
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "mpl_fig = hvplot.render(violent_crime, backend='matplotlib')\n",
    "axes = mpl_fig.get_axes()\n",
    "axes[0].set_title('Violent crime')\n",
    "mpl_fig"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3fbf40c6",
   "metadata": {},
   "outputs": [],
   "source": [
    "from plotly.graph_objects import Figure\n",
    "\n",
    "plotly_fig = hvplot.render(violent_crime, backend='plotly')\n",
    "fig = Figure(plotly_fig).update_layout(title='Violent crime')\n",
    "fig"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb4230a0",
   "metadata": {},
   "source": [
    "As demonstrated on this page hvPlot offers you the ability to choose your favorite plotting extension among those supported by [HoloViews](https://holoviews.org/), on which hvPlot is built."
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
